package com.framework.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.framework.core.common.bo.LoginUser;
import com.framework.core.common.bo.SysRoleBO;
import com.framework.core.common.bo.SysUserBO;
import com.framework.core.common.constant.Constants;
import com.framework.core.common.enums.DeletedEnum;
import com.framework.core.common.enums.GrantTypeEnum;
import com.framework.core.common.enums.StatusEnum;
import com.framework.core.common.enums.UserPlatformEnum;
import com.framework.core.exception.CustomException;
import com.framework.core.util.AddressUtil;
import com.framework.core.util.IpUtil;
import com.framework.core.util.SecurityUtil;
import com.framework.system.entity.SysRole;
import com.framework.system.entity.SysUser;
import com.framework.system.entity.dto.LoginDTO;
import com.framework.system.mapper.SysUserMapper;
import com.framework.system.service.ISysMenuService;
import com.framework.system.service.ISysRoleService;
import com.framework.system.service.ISysUserLoginService;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户实现类
 *
 * @author Kevin
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysUserLoginServiceImpl implements ISysUserLoginService {

    private ISysMenuService sysMenuService;

    private SysUserMapper sysUserMapper;

    private ISysRoleService sysRoleService;

    @Override
    public String login(LoginDTO req) {
        SysUser sysUser = null;
        if (StrUtil.isBlank(req.getUsername())) {
            throw new CustomException("用户名不能为空");
        }
        if (StrUtil.isBlank(req.getPassword())) {
            throw new CustomException("密码不能为空");
        }
        sysUser = sysUserMapper.selectOne(Wrappers.lambdaQuery(SysUser.class)
                .eq(SysUser::getAccount, req.getUsername())
                .eq(SysUser::getDeleted, DeletedEnum.NO.getCode()));
        if (Objects.isNull(sysUser)) {
            log.info("登录用户：{}不存在", req.getUsername());
            throw new CustomException("登录用户不存在");
        }
        if (!SecurityUtil.matchesPassword(req.getPassword(), sysUser.getPassword())) {
            throw new CustomException("账号或密码不正确");
        }
        if (sysUser.getStatus().equals(StatusEnum.NO.getCode())) {
            log.info("登录用户：{}已被停用", req.getUsername());
            throw new CustomException("对不起，您的账号已被停用");
        }
        log.info("登录用户：{}", req.getUsername());
        SysUserBO sysUserBO = BeanUtil.copyProperties(sysUser, SysUserBO.class);
        // 查询角色列表
        List<SysRole> sysRoleList = sysRoleService.selectSysRoleByUserId(sysUser.getId());
        // 设置角色列表
        sysUserBO.setRoles(sysRoleList.stream().map(item -> BeanUtil.copyProperties(item, SysRoleBO.class)).collect(Collectors.toList()));
        // 查询权限标识
        Set<String> permissions = Sets.newHashSet();
        if (SecurityUtil.isRootGroup(sysRoleList.stream().map(SysRole::getRoleCode).collect(Collectors.toSet()))) {
            permissions.add(Constants.ALL_PERMISSION);
        } else {
            permissions = sysMenuService.getPermissionsByUserId(sysUser.getId());
        }
        // 登录
        StpUtil.login(sysUser.getId());
        LoginUser loginUser = new LoginUser();
        loginUser.setToken(StpUtil.getTokenValue());
        loginUser.setUserPlatform(UserPlatformEnum.WEB.getCode());
        loginUser.setGrantType(req.getGrantType());
        loginUser.setSysUser(sysUserBO);
        if (req.getGrantType().equals(GrantTypeEnum.USERNAME_PASSWORD.getCode())) {
            loginUser.setUsername(req.getUsername());
        }
        if (req.getGrantType().equals(GrantTypeEnum.MOBILE_CODE.getCode())) {
            loginUser.setUsername(req.getMobile());
        }
        loginUser.setLoginTime(new Date());
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        String ipAddress = IpUtil.getClientIp(request);
        loginUser.setIpAddress(ipAddress);
        loginUser.setLoginLocation(AddressUtil.getRealAddressByIp(ipAddress));
        loginUser.setBrowser(userAgent.getBrowser().getName());
        loginUser.setOs(userAgent.getOs().getName());
        loginUser.setPermissions(permissions);
        // 设置用户信息
        StpUtil.getTokenSession().set(Constants.LOGIN_USER_KEY, loginUser);
        return StpUtil.getTokenValue();
    }

}
